using System;
using System.IO.Ports;

namespace SerialPortLibrary
{
    /// <summary>
    /// 串行通讯服务
    /// </summary>
    /// <remarks></remarks>
    internal class SerialPort : DataPublish, ISerialPort
    {
        public long SendBytes { get; set; }
        public long ReceiveBytes { get; set; }

        private System.IO.Ports.SerialPort ComHandle;
        /// <summary>
        /// 发送超时时间 秒
        /// </summary>
        public int SendTimeOut
        {
            get { return ComHandle.WriteTimeout; }
            set { ComHandle.WriteTimeout = value; }
        }
        /// <summary>
        /// 接收超时时间 秒
        /// </summary>
        public int ReceiveTimeOut
        {
            get { return ComHandle.ReadTimeout; }
            set { ComHandle.ReadTimeout = value; }
        }
        /// <summary>
        /// 发送缓冲区大小
        /// </summary>
        public int ReadBufferSize
        {
            get { return ComHandle.ReadBufferSize; }
            set { ComHandle.ReadBufferSize = value; }
        }
        /// <summary>
        /// 接受缓冲区大小
        /// </summary>
        public int WriteBufferSize
        {
            get { return ComHandle.WriteBufferSize; }
            set { ComHandle.WriteBufferSize = value; }
        }
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="COM"></param>
        /// <param name="BaudRate"></param>
        /// <param name="Parity"></param>
        /// <param name="DataBits"></param>
        /// <param name="StopBit"></param>
        internal SerialPort(string COM, int BaudRate, Parity Parity, int DataBits, StopBits StopBit)
        {
            ComHandle = new System.IO.Ports.SerialPort(COM, BaudRate, Parity, DataBits, StopBit) { ReadBufferSize = 4096, WriteBufferSize = 4096, ReceivedBytesThreshold = 1 };
            ComHandle.DataReceived += ComHandle_DataReceived;
            ComHandle.ErrorReceived += ComHandle_ErrorReceived;
        }

        private void ComHandle_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            serialdata.Error.ErrorType = 2;
            serialdata.Error.ErrorMessage = e.EventType.ToString();
            DataPublishEventArgs args = new DataPublishEventArgs(serialdata);
            OnDataPublishEvent(args);
        }

        /// <summary>
        /// 启动发送命令
        /// </summary>
        /// <param name="list"></param>
        public void Send(ISerialData data)
        {
            if (data.Data == null || data.Data.Length < 1) { return; }
            if (!ComHandle.IsOpen) { return; }
            serialdata = data;
            serialdata.ComID = ComHandle.PortName;
            byte[] by = data.Data;
            SendBytes += by.Length;
            ComHandle.DiscardOutBuffer(); //清空缓冲区
            ComHandle.DiscardInBuffer();
            try
            {
                ComHandle.Write(by, 0, by.Length);
            }
            catch (Exception Error)
            {
                serialdata.Error.ErrorType = 1;
                serialdata.Error.ErrorMessage = Error.Message;
                DataPublishEventArgs args = new DataPublishEventArgs(serialdata);
                OnDataPublishEvent(args);
            }
        }
        /// <summary>
        /// 接收事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ComHandle_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (e.EventType != System.IO.Ports.SerialData.Chars) { return; }
            try
            {
                System.IO.Ports.SerialPort port = sender as System.IO.Ports.SerialPort;
                int ReceiveCount = port.BytesToRead;
                byte[] by = new byte[ReceiveCount];
                port.Read(by, 0, by.Length);
                ReceiveBytes += by.Length;
                serialdata.Data = by;
            }
            catch (Exception Error)
            {
                serialdata.Error.ErrorType = 3;
                serialdata.Error.ErrorMessage = Error.Message;
            }
            finally
            {
                DataPublishEventArgs args = new DataPublishEventArgs(serialdata);
                OnDataPublishEvent(args);
            }
        }
        /// <summary>
        /// 获取串口状态
        /// </summary>
        public bool IsOpen
        {
            get { return ComHandle.IsOpen; }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool ClosePort()
        {
            try
            {
                if (ComHandle.IsOpen)
                {
                    serialdata.Error.ErrorType = -1;
                    DataPublishEventArgs args = new DataPublishEventArgs(serialdata);
                    OnDataPublishEvent(args);
                    ComHandle.Close();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool OpenPort()
        {
            try
            {
                if (!ComHandle.IsOpen)
                {
                    ComHandle.Open();
                }
                else
                {
                    return false;
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
